package cn.com.anypay.manager.service.auth.strategy.impl;

import cn.com.anypay.manager.common.exception.WeChatAuthException;
import cn.com.anypay.manager.common.utils.WeChatAuthDataUtils;
import cn.com.anypay.manager.dto.wechat.WeChatAccessToken;
import cn.com.anypay.manager.dto.wechat.WeChatUserInfo;
import cn.com.anypay.manager.miaoma.sysuser.SysUserEntity;
import cn.com.anypay.manager.miaoma.sysuserauth.SysUserAuthEntity;
import cn.com.anypay.manager.service.WeChatService;
import cn.com.anypay.manager.service.auth.model.AuthRequest;
import cn.com.anypay.manager.service.auth.model.AuthResult;
import cn.com.anypay.manager.service.auth.strategy.AbstractAuthStrategy;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import jakarta.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;

/**
 * 微信认证策略
 * 实现微信扫码登录认证逻辑
 */
@Slf4j
@Component
public class WeChatAuthStrategy extends AbstractAuthStrategy {

    @Autowired
    private WeChatService weChatService;

    @Autowired
    private ObjectMapper objectMapper;

    @Override
    public String getAuthType() {
        return "wechat";
    }

    @Override
    protected boolean doAuthenticate(AuthRequest request, SysUserEntity user,
                                   HttpServletRequest servletRequest) {
        log.info("开始执行微信认证: identifier={}", request.getIdentifier());

        try {
            // 验证授权码
            String code = request.getCredential();
            if (!StringUtils.hasText(code)) {
                log.warn("微信授权码为空: identifier={}", request.getIdentifier());
                return false;
            }

            // 获取访问令牌
            WeChatAccessToken accessToken = weChatService.getAccessToken(code);
            if (accessToken == null || !accessToken.isValid()) {
                log.warn("获取微信访问令牌失败: identifier={}", request.getIdentifier());
                return false;
            }

            // 获取微信用户信息
            WeChatUserInfo weChatUserInfo = weChatService.getUserInfo(
                accessToken.getAccessToken(), accessToken.getOpenId());
            if (weChatUserInfo == null || !weChatUserInfo.isValid()) {
                log.warn("获取微信用户信息失败: identifier={}", request.getIdentifier());
                return false;
            }

            // 验证OpenID是否匹配
            if (!accessToken.getOpenId().equals(request.getIdentifier())) {
                log.warn("微信OpenID不匹配: expected={}, actual={}", 
                    request.getIdentifier(), accessToken.getOpenId());
                return false;
            }

            // 更新用户的微信信息
            updateUserWeChatInfo(user, weChatUserInfo);

            log.info("微信认证成功: userId={}, openId={}", user.getId(), weChatUserInfo.getOpenId());
            return true;

        } catch (WeChatAuthException e) {
            log.warn("微信认证失败: identifier={}, error={}", request.getIdentifier(), e.getMessage());
            return false;
        } catch (Exception e) {
            log.error("微信认证过程发生异常: identifier={}", request.getIdentifier(), e);
            return false;
        }
    }

    @Override
    protected SysUserEntity findOrCreateUser(AuthRequest request, HttpServletRequest servletRequest) {
        String openId = request.getIdentifier();
        log.info("查找或创建微信用户: openId={}", openId);

        try {
            // 首先尝试通过微信OpenID查找现有用户
            SysUserAuthEntity authEntity = sysUserAuthService.getByAuthTypeAndKey(getAuthType(), openId);
            if (authEntity != null && isAuthEntityValid(authEntity)) {
                // 找到现有的微信认证记录，获取对应的用户
                SysUserEntity user = sysUserService.getById(authEntity.getUserId());
                if (user != null && isUserActive(user)) {
                    log.info("找到现有微信用户: userId={}, openId={}", user.getId(), openId);
                    return user;
                }
            }

            // 如果没有找到现有用户，需要获取微信用户信息来创建新用户
            String code = request.getCredential();
            WeChatAccessToken accessToken = weChatService.getAccessToken(code);
            if (accessToken == null || !accessToken.isValid()) {
                log.warn("无法获取微信访问令牌创建用户: openId={}", openId);
                return null;
            }

            WeChatUserInfo weChatUserInfo = weChatService.getUserInfo(
                accessToken.getAccessToken(), accessToken.getOpenId());
            if (weChatUserInfo == null || !weChatUserInfo.isValid()) {
                log.warn("无法获取微信用户信息创建用户: openId={}", openId);
                return null;
            }

            // 创建新用户
            SysUserEntity newUser = createUserFromWeChatInfo(weChatUserInfo);
            if (newUser == null) {
                log.error("创建微信用户失败: openId={}", openId);
                return null;
            }

            // 创建微信认证记录
            createWeChatAuthRecord(newUser.getId(), weChatUserInfo);

            log.info("成功创建微信用户: userId={}, openId={}", newUser.getId(), openId);
            return newUser;

        } catch (Exception e) {
            log.error("查找或创建微信用户时发生异常: openId={}", openId, e);
            return null;
        }
    }

    @Override
    protected void validateRequest(AuthRequest request) {
        super.validateRequest(request);

        // 微信认证的特殊验证
        String openId = request.getIdentifier();
        if (!isValidOpenId(openId)) {
            throw new IllegalArgumentException("无效的微信OpenID格式");
        }

        String code = request.getCredential();
        if (!isValidAuthCode(code)) {
            throw new IllegalArgumentException("无效的微信授权码格式");
        }
    }

    /**
     * 验证微信OpenID格式
     */
    private boolean isValidOpenId(String openId) {
        return WeChatAuthDataUtils.isValidOpenId(openId);
    }

    /**
     * 验证微信授权码格式
     */
    private boolean isValidAuthCode(String code) {
        return StringUtils.hasText(code) && 
               code.length() >= 10 && 
               code.length() <= 100;
    }

    /**
     * 从微信用户信息创建系统用户
     */
    private SysUserEntity createUserFromWeChatInfo(WeChatUserInfo weChatUserInfo) {
        try {
            SysUserEntity user = new SysUserEntity();
            
            // 生成唯一的用户名（使用微信OpenID）
            String username = WeChatAuthDataUtils.generateDefaultUsername(weChatUserInfo.getOpenId());
            user.setUsername(username);
            
            // 设置用户基本信息
            user.setRealName(StringUtils.hasText(weChatUserInfo.getNickname()) ? 
                weChatUserInfo.getNickname() : "微信用户");
            user.setAvatar(weChatUserInfo.getHeadImgUrl());
            user.setStatus(1); // 启用状态
            user.setCreatedTime(LocalDateTime.now());
            user.setUpdatedTime(LocalDateTime.now());

            // 保存用户
            boolean saved = sysUserService.save(user);
            if (!saved) {
                log.error("保存微信用户失败: openId={}", weChatUserInfo.getOpenId());
                return null;
            }

            return user;

        } catch (Exception e) {
            log.error("创建微信用户时发生异常: openId={}", weChatUserInfo.getOpenId(), e);
            return null;
        }
    }

    /**
     * 创建微信认证记录
     */
    private void createWeChatAuthRecord(Long userId, WeChatUserInfo weChatUserInfo) {
        try {
            SysUserAuthEntity authEntity = new SysUserAuthEntity();
            authEntity.setUserId(userId);
            authEntity.setAuthType(getAuthType());
            authEntity.setAuthIdentifierKey(weChatUserInfo.getOpenId());
            
            // 将微信用户信息存储在extraData中
            authEntity.setExtraData(WeChatAuthDataUtils.buildExtraData(weChatUserInfo));
            
            authEntity.setStatus(1); // 启用状态
            authEntity.setIsPrimary(1); // 设为主要认证方式
            authEntity.setMaxErrorCount(5);
            authEntity.setErrorCount(0);
            authEntity.setLoginCount(0);
            authEntity.setCreatedTime(LocalDateTime.now());
            authEntity.setUpdatedTime(LocalDateTime.now());

            boolean saved = sysUserAuthService.save(authEntity);
            if (!saved) {
                log.error("保存微信认证记录失败: userId={}, openId={}", 
                    userId, weChatUserInfo.getOpenId());
            }

        } catch (Exception e) {
            log.error("创建微信认证记录时发生异常: userId={}, openId={}", 
                userId, weChatUserInfo.getOpenId(), e);
        }
    }

    /**
     * 更新用户的微信信息
     */
    private void updateUserWeChatInfo(SysUserEntity user, WeChatUserInfo weChatUserInfo) {
        try {
            boolean needUpdate = false;

            // 更新头像（如果用户没有头像或微信头像更新了）
            if (StringUtils.hasText(weChatUserInfo.getHeadImgUrl()) && 
                !weChatUserInfo.getHeadImgUrl().equals(user.getAvatar())) {
                user.setAvatar(weChatUserInfo.getHeadImgUrl());
                needUpdate = true;
            }

            // 更新真实姓名（如果用户没有真实姓名）
            if (!StringUtils.hasText(user.getRealName()) && 
                StringUtils.hasText(weChatUserInfo.getNickname())) {
                user.setRealName(weChatUserInfo.getNickname());
                needUpdate = true;
            }

            if (needUpdate) {
                user.setUpdatedTime(LocalDateTime.now());
                sysUserService.updateById(user);
                log.info("更新用户微信信息: userId={}, openId={}", 
                    user.getId(), weChatUserInfo.getOpenId());
            }

            // 更新认证记录中的微信信息
            updateWeChatAuthRecord(user.getId(), weChatUserInfo);

        } catch (Exception e) {
            log.error("更新用户微信信息时发生异常: userId={}, openId={}", 
                user.getId(), weChatUserInfo.getOpenId(), e);
        }
    }

    /**
     * 更新微信认证记录中的用户信息
     */
    private void updateWeChatAuthRecord(Long userId, WeChatUserInfo weChatUserInfo) {
        try {
            SysUserAuthEntity authEntity = sysUserAuthService.getByAuthTypeAndKey(
                getAuthType(), weChatUserInfo.getOpenId());
            
            if (authEntity != null) {
                // 更新extraData中的微信用户信息
                authEntity.setExtraData(WeChatAuthDataUtils.buildExtraData(weChatUserInfo));
                authEntity.setUpdatedTime(LocalDateTime.now());
                
                sysUserAuthService.updateById(authEntity);
                log.debug("更新微信认证记录: userId={}, openId={}", 
                    userId, weChatUserInfo.getOpenId());
            }

        } catch (Exception e) {
            log.error("更新微信认证记录时发生异常: userId={}, openId={}", 
                userId, weChatUserInfo.getOpenId(), e);
        }
    }



    /**
     * 获取用户权限信息
     * 与其他认证方式保持一致，使用统一的权限获取逻辑
     */
    @Override
    protected Object getUserPermissions(SysUserEntity user) {
        try {
            // 使用与其他认证方式一致的权限获取逻辑
            return sysUserService.getUserPermissions(user.getId());
        } catch (Exception e) {
            log.error("获取微信用户权限失败: userId={}", user.getId(), e);
            // 返回空权限列表，与其他认证方式的错误处理保持一致
            return java.util.Collections.emptyList();
        }
    }

    /**
     * 构建用户信息，确保与其他认证方式保持一致的响应格式
     * 同时添加微信特有信息
     */
    @Override
    protected Map<String, Object> buildUserInfo(SysUserEntity user) {
        // 使用父类的标准用户信息构建逻辑，确保格式一致
        Map<String, Object> userInfo = super.buildUserInfo(user);
        
        try {
            // 添加微信认证标识，与其他认证方式保持一致的标识方式
            userInfo.put("authType", getAuthType());
            
            // 获取微信认证记录中的额外信息
            SysUserAuthEntity authEntity = sysUserAuthService.getUserAuthList(user.getId()).stream()
                .filter(auth -> getAuthType().equals(auth.getAuthType()) && auth.getStatus() == 1)
                .findFirst()
                .orElse(null);
            
            if (authEntity != null && StringUtils.hasText(authEntity.getExtraData())) {
                try {
                    Map<String, Object> weChatInfo = WeChatAuthDataUtils.parseExtraData(authEntity.getExtraData());
                    // 只添加非敏感的微信信息，确保数据安全
                    Map<String, Object> safeWeChatInfo = new HashMap<>();
                    safeWeChatInfo.put("nickname", weChatInfo.get("nickname"));
                    safeWeChatInfo.put("headImgUrl", weChatInfo.get("headImgUrl"));
                    safeWeChatInfo.put("bindTime", authEntity.getCreatedTime());
                    
                    userInfo.put("weChatInfo", safeWeChatInfo);
                } catch (Exception parseException) {
                    log.warn("解析微信用户信息失败: userId={}", user.getId(), parseException);
                }
            }
            
        } catch (Exception e) {
            log.error("构建微信用户信息时发生异常: userId={}", user.getId(), e);
            // 即使微信信息获取失败，也要确保返回基础用户信息，保持与其他认证方式一致的容错性
        }
        
        return userInfo;
    }

    /**
     * 绑定微信账户到现有用户
     * 
     * @param userId 要绑定的用户ID
     * @param code 微信授权码
     * @return 绑定结果
     */
    public boolean bindWeChatAccount(Long userId, String code) {
        log.info("开始绑定微信账户: userId={}", userId);

        try {
            // 验证用户是否存在
            SysUserEntity user = sysUserService.getById(userId);
            if (user == null || !isUserActive(user)) {
                log.warn("用户不存在或已禁用: userId={}", userId);
                return false;
            }

            // 获取微信访问令牌
            WeChatAccessToken accessToken = weChatService.getAccessToken(code);
            if (accessToken == null || !accessToken.isValid()) {
                log.warn("获取微信访问令牌失败: userId={}", userId);
                return false;
            }

            // 获取微信用户信息
            WeChatUserInfo weChatUserInfo = weChatService.getUserInfo(
                accessToken.getAccessToken(), accessToken.getOpenId());
            if (weChatUserInfo == null || !weChatUserInfo.isValid()) {
                log.warn("获取微信用户信息失败: userId={}", userId);
                return false;
            }

            // 检查该微信账户是否已经绑定到其他用户
            SysUserAuthEntity existingAuth = sysUserAuthService.getByAuthTypeAndKey(
                getAuthType(), weChatUserInfo.getOpenId());
            if (existingAuth != null) {
                if (existingAuth.getUserId().equals(userId)) {
                    log.info("微信账户已绑定到当前用户: userId={}, openId={}", 
                        userId, weChatUserInfo.getOpenId());
                    // 更新微信信息
                    updateWeChatAuthRecord(userId, weChatUserInfo);
                    return true;
                } else {
                    log.warn("微信账户已绑定到其他用户: openId={}, boundUserId={}, requestUserId={}", 
                        weChatUserInfo.getOpenId(), existingAuth.getUserId(), userId);
                    return false;
                }
            }

            // 创建微信认证记录
            createWeChatAuthRecord(userId, weChatUserInfo);

            // 更新用户信息
            updateUserWeChatInfo(user, weChatUserInfo);

            log.info("成功绑定微信账户: userId={}, openId={}", userId, weChatUserInfo.getOpenId());
            return true;

        } catch (Exception e) {
            log.error("绑定微信账户时发生异常: userId={}", userId, e);
            return false;
        }
    }

    /**
     * 解绑微信账户
     * 
     * @param userId 用户ID
     * @return 解绑结果
     */
    public boolean unbindWeChatAccount(Long userId) {
        log.info("开始解绑微信账户: userId={}", userId);

        try {
            // 验证用户是否存在
            SysUserEntity user = sysUserService.getById(userId);
            if (user == null) {
                log.warn("用户不存在: userId={}", userId);
                return false;
            }

            // 检查用户是否还有其他认证方式
            if (!canUnbindWeChatAccount(userId)) {
                log.warn("不能解绑微信账户，用户没有其他认证方式: userId={}", userId);
                return false;
            }

            // 删除微信认证记录
            int deletedCount = sysUserAuthService.removeByUserIdAndAuthType(userId, getAuthType());
            
            if (deletedCount > 0) {
                log.info("成功解绑微信账户: userId={}, deletedRecords={}", userId, deletedCount);
                return true;
            } else {
                log.warn("未找到要解绑的微信认证记录: userId={}", userId);
                return false;
            }

        } catch (Exception e) {
            log.error("解绑微信账户时发生异常: userId={}", userId, e);
            return false;
        }
    }

    /**
     * 检查是否可以解绑微信账户
     * 确保用户至少有一种其他认证方式
     */
    private boolean canUnbindWeChatAccount(Long userId) {
        try {
            // 获取用户的所有认证方式
            var authList = sysUserAuthService.getUserAuthList(userId);
            
            // 计算非微信认证方式的数量
            long nonWeChatAuthCount = authList.stream()
                .filter(auth -> !getAuthType().equals(auth.getAuthType()))
                .filter(auth -> auth.getStatus() == 1) // 只计算启用的认证方式
                .count();
            
            return nonWeChatAuthCount > 0;
            
        } catch (Exception e) {
            log.error("检查是否可以解绑微信账户时发生异常: userId={}", userId, e);
            return false;
        }
    }

    /**
     * 检查用户是否已绑定微信账户
     * 
     * @param userId 用户ID
     * @return 是否已绑定
     */
    public boolean isWeChatAccountBound(Long userId) {
        try {
            var authList = sysUserAuthService.getUserAuthList(userId);
            return authList.stream()
                .anyMatch(auth -> getAuthType().equals(auth.getAuthType()) && auth.getStatus() == 1);
        } catch (Exception e) {
            log.error("检查微信账户绑定状态时发生异常: userId={}", userId, e);
            return false;
        }
    }

    /**
     * 获取用户绑定的微信账户信息
     * 
     * @param userId 用户ID
     * @return 微信账户信息
     */
    public Map<String, Object> getWeChatAccountInfo(Long userId) {
        try {
            SysUserAuthEntity authEntity = sysUserAuthService.getUserAuthList(userId).stream()
                .filter(auth -> getAuthType().equals(auth.getAuthType()) && auth.getStatus() == 1)
                .findFirst()
                .orElse(null);

            if (authEntity == null || !StringUtils.hasText(authEntity.getExtraData())) {
                return null;
            }

            Map<String, Object> weChatInfo = WeChatAuthDataUtils.parseExtraData(authEntity.getExtraData());
            
            // 添加绑定时间信息
            weChatInfo.put("bindTime", authEntity.getCreatedTime());
            weChatInfo.put("lastLoginTime", authEntity.getLastLoginTime());
            weChatInfo.put("loginCount", authEntity.getLoginCount());
            
            return weChatInfo;

        } catch (Exception e) {
            log.error("获取微信账户信息时发生异常: userId={}", userId, e);
            return null;
        }
    }

    /**
     * 记录微信认证相关的审计日志
     * 确保与其他认证方式保持一致的日志格式和内容
     * 
     * @param userId 用户ID
     * @param openId 微信OpenID
     * @param operation 操作类型
     * @param result 操作结果
     * @param errorMessage 错误信息（可选）
     * @param request HTTP请求
     */
    private void recordWeChatAuthLog(Long userId, String openId, String operation, 
                                   String result, String errorMessage, HttpServletRequest request) {
        try {
            // 使用统一的日志记录服务，确保与其他认证方式一致
            sysUserAuthLogService.recordAuthLog(userId, getAuthType(), openId, 
                operation, result, errorMessage, request);
            
            log.info("微信认证日志记录成功: userId={}, openId={}, operation={}, result={}", 
                userId, openId, operation, result);
                
        } catch (Exception e) {
            log.error("记录微信认证日志失败: userId={}, openId={}, operation={}", 
                userId, openId, operation, e);
        }
    }

    /**
     * 重写认证失败处理，添加微信特有的错误处理逻辑
     * 同时确保与其他认证方式保持一致的处理流程
     */
    @Override
    protected AuthResult handleAuthFailure(SysUserEntity user, AuthRequest request,
                                         HttpServletRequest servletRequest, String errorMessage) {
        try {
            // 对于微信认证，提供更友好的错误信息
            String friendlyErrorMessage = translateWeChatError(errorMessage);
            
            // 调用父类的标准失败处理流程，确保与其他认证方式一致
            return super.handleAuthFailure(user, request, servletRequest, friendlyErrorMessage);
            
        } catch (Exception e) {
            log.error("处理微信认证失败时发生异常: identifier={}", request.getIdentifier(), e);
            // 确保即使异常情况下也返回一致的错误格式
            return AuthResult.failure("微信认证失败，请稍后重试");
        }
    }

    /**
     * 将微信特有的错误信息转换为用户友好的错误信息
     * 确保错误信息的一致性和用户体验
     */
    private String translateWeChatError(String originalError) {
        if (originalError == null) {
            return "微信认证失败";
        }
        
        // 将技术性错误信息转换为用户友好的信息
        if (originalError.contains("access_token")) {
            return "微信授权已过期，请重新扫码登录";
        } else if (originalError.contains("invalid_code")) {
            return "微信授权码无效，请重新扫码登录";
        } else if (originalError.contains("network") || originalError.contains("timeout")) {
            return "网络连接异常，请稍后重试";
        } else if (originalError.contains("openid")) {
            return "微信用户信息获取失败，请重新尝试";
        }
        
        // 对于其他错误，返回通用的友好信息
        return "微信登录失败，请稍后重试";
    }

    /**
     * 根据微信OpenID查找用户
     * 
     * @param openId 微信OpenID
     * @return 用户信息，如果未找到返回null
     */
    public SysUserEntity findUserByOpenId(String openId) {
        try {
            SysUserAuthEntity authEntity = sysUserAuthService.getByAuthTypeAndKey(getAuthType(), openId);
            if (authEntity != null && isAuthEntityValid(authEntity)) {
                return sysUserService.getById(authEntity.getUserId());
            }
            return null;
        } catch (Exception e) {
            log.error("根据OpenID查找用户时发生异常: openId={}", openId, e);
            return null;
        }
    }
}